package com.extra_archive.project.iisu.view.list 
{
	import iisu.Vector3;
	import iisu.iisuEvent.PressReleaseEvent;

	import com.extra_archive.framework.core.mvc.controller.IController;
	import com.extra_archive.framework.core.mvc.model.IModel;
	import com.extra_archive.framework.core.mvc.view.CompositeView;
	import com.extra_archive.project.iisu.controller.ARController;
	import com.extra_archive.project.iisu.model.ARModel;
	import com.extra_archive.project.iisu.model.ARModelEvent;
	import com.extra_archive.project.iisu.view.IARState;
	import com.greensock.TweenMax;
	import com.greensock.easing.Back;
	import com.greensock.easing.Cubic;

	import org.papervision3d.materials.BitmapMaterial;
	import org.papervision3d.objects.DisplayObject3D;
	import org.papervision3d.objects.primitives.Plane;

	import flash.events.Event;
	import flash.utils.setTimeout;

	/**
	 * @class name : ARListCarouselView
	 * @author : implict (http://extra-archive.com)
	 * @date : 2010. 5. 4.
	 * @description :
	 */
	public class ARListCarouselView extends CompositeView implements IARState 
	{
		private var _planesContainer : DisplayObject3D;
		private var _prevBodyPositionX : int = 0;
		private var _bodyDistance : int = 0;
		private var _prevRightHandY : Number = 0;
		private var _prevLeftHandY : Number = 0;
		private var _playTween : TweenMax;
		private var _selectedPlane : Plane;
		private var _isPlayTweenComplete: Boolean;
		private var _isActive : Boolean;
		private var _isSelected : Boolean;
		
		public function ARListCarouselView(model : IModel = null, controller : IController = null)
		{
			super(model, controller);
			
			initialize();
			
			ARModel(_model).gesture.addEventListener(PressReleaseEvent.RELEASE_TWO_HANDS, onTriggerUp);
		}
		
		//--------------------------------------------------------------------------
		//
		//    Public Methods
		//
		//--------------------------------------------------------------------------
		
		override public function initialize() : void
		{
			createPlanesContainer();
			createPlanes();
		}
		
		override public function update(event : Event = null) : void
		{
			if (!ARModel(_model).gesture.isGestureControl) play();
			else
			{
				if (ARModel(_model).gesture.isUserActive) play();
				else stop();
			}
			
			if (!_isActive || _isSelected) return;
			
			setSelectedPlane();
			setPlaneAlpha();
			setPlaneScale();
			setListRotation();
			setListPosition();

			if (!ARModel(_model).gesture.isGestureControl) return;
			if (ARModel(_model).gesture.rightHand.z > 1.2 && ARModel(_model).gesture.leftHand.z > 1.2) select();
		}

		public function live() : void
		{
			ARModel(_model).space3DView.scene.addChild(_planesContainer);
			if (_isSelected) resetPlanes();
		}

		public function kill() : void
		{
			ARModel(_model).space3DView.scene.removeChild(_planesContainer);
		}
		
		//--------------------------------------------------------------------------
		//
		//    Event Listeners
		//
		//--------------------------------------------------------------------------
		
		private function onTriggerUp(event : PressReleaseEvent) : void 
		{
			select();
		}

		//--------------------------------------------------------------------------
		//
		//    Private Methods
		//
		//--------------------------------------------------------------------------
		
		private function dispatchListToDetailEvent() : void
		{
			ARModel(_model).gesture.dispatchEvent(new ARModelEvent(ARModelEvent.LIST_TO_DETAIL));
		}
		
		private function createPlanesContainer() : void 
		{
			_planesContainer = new DisplayObject3D();
			_planesContainer.scale = 0.1;
			_planesContainer.y = 0;
		}
		
		private function createPlanes() : void 
		{
			var plane : Plane;
			var material : BitmapMaterial;
			var i : uint, len : uint = ARModel(_model).assetManager.listImgs.length;
			for (i; i < len; ++i)
			{
				material = new BitmapMaterial(ARModel(_model).assetManager.listImgs[i].bitmapData);
				material.smooth = true;
				material.doubleSided = true;
				plane = new Plane(material, uint(material.bitmap.width), uint(material.bitmap.height));
				plane.name = "plane" + i;
				plane.useOwnContainer = true;
				plane.scale = 0.2;
				plane.alpha = 0;
				plane.x = 150 * Math.cos(Math.PI * 2 / len * i);
				plane.z = 150 * Math.sin(Math.PI * 2 / len * i);
				plane.rotationY = -360 / len * i - 90;
				_planesContainer.addChild(plane);
			}
		}
		
		private function resetPlanes() : void 
		{
			_isSelected = false;
			_isPlayTweenComplete = false;
			var plane : Plane;
			var ta : Number, tx : int, tz : int;
			var i : uint, len : uint = ARModel(_model).assetManager.listImgs.length;
			for (i; i < len; ++i)
			{
				plane = Plane(_planesContainer.getChildByName("plane" + i));
				tx = 150 * Math.cos(Math.PI * 2 / len * i);
				tz = 150 * Math.sin(Math.PI * 2 / len * i);
				if (tz > -100) ta = 1 - (tz + 100) / 200;
				else ta = 1;
				if (plane != _selectedPlane) TweenMax.to(plane, 0.7, {delay : 0.6, alpha : 1, x : tx, z : tz, ease: Back.easeOut});
			}
			_selectedPlane.y = -30;
			
			TweenMax.to(_selectedPlane, 0.4, {rotationX:_selectedPlane.rotationX + 90, ease: Cubic.easeOut});	
			TweenMax.to(_selectedPlane, 0.5, {delay : 0.2, y : 0, ease: Cubic.easeOut, onComplete: function() : void
			{
				
			}});
			
			setTimeout(function():void{_isPlayTweenComplete = true;}, 1400);
		}
		
		private function select() : void
		{
			TweenMax.to(_selectedPlane, 0.4, {y : 100, ease : Cubic.easeOut});
			var plane : Plane;
			var i : uint, len : uint = ARModel(_model).assetManager.listImgs.length;
			for (i; i < len; ++i)
			{
				plane = Plane(_planesContainer.getChildByName("plane" + i));
				if (plane != _selectedPlane) TweenMax.to(plane, 0.5, {alpha : 0, x : 0, z : 0, ease: Cubic.easeIn});
			}
			TweenMax.to(_selectedPlane, 0.6, {y : 80, ease: Cubic.easeOut});
			TweenMax.to(_selectedPlane, 0.3, {delay : 0.55, rotationX : _selectedPlane.rotationX - 90, ease : Cubic.easeIn});	
			
			
			ARController(_controller).changeSection(uint(_selectedPlane.name.slice(5)));
			setTimeout(dispatchListToDetailEvent, 850);
			
			_isSelected = true;
		}
		
		/**
		 * 등장 모션
		 */
		private function play() : void
		{
			if (_isActive) return;
			_playTween = TweenMax.to(_planesContainer, 1.5, {scale : 1, rotationY : _planesContainer.rotationY + 360, alpha : 1, ease : Cubic.easeOut, onComplete : onPlayTweenComplete});
			setPlaneAlpha();
			var plane : Plane;
			var i : uint, len : uint = ARModel(_model).assetManager.listImgs.length;
			for (i; i < len; ++i)
			{
				plane = Plane(_planesContainer.getChildByName("plane" + i));
				TweenMax.from(plane, 0.5, {alpha : 0});
			}
			_isActive = true;
			
			function onPlayTweenComplete() : void
			{
				_isPlayTweenComplete = true;
			}
		}

		/**
		 * 사라지는 모션
		 */
		private function stop() : void
		{
			if (!_isActive) return;
			
			var plane : Plane;
			var i : uint, len : uint = ARModel(_model).assetManager.listImgs.length;
			for (i; i < len; ++i)
			{
				plane = Plane(_planesContainer.getChildByName("plane" + i));
				TweenMax.to(plane, 0.5, {delay: 0.3, alpha : 0});
			}
			TweenMax.to(_planesContainer, 1.5, {scale : 0.1, rotationY : _planesContainer.rotationY - 360, ease : Cubic.easeOut});
			
			_isActive = false;
			_isPlayTweenComplete = false;
		}

		private function setPlaneAlpha() : void 
		{
			var plane : Plane;
			var i : uint, len : uint = ARModel(_model).assetManager.listImgs.length;
			for (i; i < len; ++i)
			{
				plane = Plane(_planesContainer.getChildByName("plane" + i));
				if (plane.sceneZ > -100) plane.alpha = 1 - (plane.sceneZ + 100) / 200;
				else plane.alpha = 1;
			}
		}

		private function setPlaneScale() : void 
		{
			var plane : Plane;
			var i : uint, len : uint = ARModel(_model).assetManager.listImgs.length;
			for (i; i < len; ++i)
			{
				plane = Plane(_planesContainer.getChildByName("plane" + i));
				if (plane == _selectedPlane) TweenMax.to(plane, 0.4, {scale : 0.55, ease: Cubic.easeOut});
				else TweenMax.to(plane, 0.4, {scale : 0.35, ease: Cubic.easeOut});
			}
		}
		
		private function setSelectedPlane() : void
		{
			var plane : Plane;
			var i : uint, len : uint = ARModel(_model).assetManager.listImgs.length;
			for (i; i < len; ++i)
			{
				plane = Plane(_planesContainer.getChildByName("plane" + i));
				if (!_selectedPlane) 
				{
					_selectedPlane = plane;
					continue;
				}
				if (plane.sceneZ < _selectedPlane.sceneZ) _selectedPlane = plane;
			}
		}
		
		private function setListRotation() : void
		{
			if (!_isPlayTweenComplete || !ARModel(_model).gesture.isGestureControl) return;
			
			var handPosX: Number = ARModel(_model).gesture.hand1.x;
			var r : int = _planesContainer.rotationY + handPosX * 20;
			var spd : Number = 0.3;
			
			if (ARModel(_model).gesture.hand1_3D.z > 0.4 && ARModel(_model).gesture.hand2_3D.z > 0.4)
			{
				var step : int = 360 / ARModel(_model).assetManager.listImgs.length;
				var gap : int = step - _planesContainer.rotationY % step;
				if (gap < step / 2) r = _planesContainer.rotationY + (step - _planesContainer.rotationY % step);
				else r = _planesContainer.rotationY - _planesContainer.rotationY % step;
				spd = 0.7;
			}
			
			TweenMax.to(_planesContainer, spd, {rotationY : r});
		}
		
		private function setListPosition() : void
		{
			var bodyPosition : Vector3 = ARModel(_model).gesture.position;
			if (!bodyPosition) return;
			if (bodyPosition.x < -0.9) bodyPosition.x = -0.9;
			//else if (bodyPosition.x > 1) bodyPosition.x = 1;
			var tx : int = bodyPosition.x * ((_model.applicationContainer.stage.stageWidth - 270) / 2);
			TweenMax.to(_planesContainer, 0.3, {x: tx});
			_bodyDistance = tx - _prevBodyPositionX;
			_prevBodyPositionX = tx;
		}
		
		private function getRightHandVelocityY() : Number
		{
			var currentRightHandY : Number = ARModel(_model).gesture.rightHand.z;
			
			var velocity : Number = currentRightHandY - _prevRightHandY;
			//trace('velocityRight: ' + (velocity));
			_prevRightHandY = currentRightHandY;
			return velocity;
		}
		
		private function getLeftHandVelocityY() : Number
		{
			var currentLeftHandY : Number = ARModel(_model).gesture.leftHand.z; 
			var velocity : Number = currentLeftHandY - _prevLeftHandY;
			//trace('velocityLeft: ' + (velocity));
			_prevLeftHandY = currentLeftHandY;
			return velocity;
		}
	}
}
